package com.business.action.wechat;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.business.wechat.bean.WeixinOrderBean;
import com.business.wechat.service.WeixinService;
import com.business.wechat.service.WeixinUtils;
import com.business.wechat.util.WxPaySignatureUtils;
import com.business.wechat.util.XMLUtil;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.util.SignUtils;

import net.sf.rose.jdbc.DBUtils;
import net.sf.rose.jdbc.PageBean;
import net.sf.rose.jdbc.dao.BeanDAO;
import net.sf.rose.jdbc.query.BeanSQL;
import net.sf.rose.jdbc.service.Service;
import net.sf.rose.util.ClassUtils;
import net.sf.rose.util.DataUtils;
import net.sf.rose.web.util.WebUtils;

/**
 * @author: xudy
 * @date: 2018/04/03 10:28
 * @description:对接微信公众号的API
 *
 */
@Controller
@RequestMapping("/wechat")
public class WechatPayAction extends WechatGenericController {

	/**
	 * 创建微信支付测试订单 openId,orderFee
	 */
	@ResponseBody
	@RequestMapping("/createOrder.do")
	public PageBean createOrder(Service service, WeixinOrderBean order) {
		PageBean res = new PageBean();
		BeanDAO dao = new BeanDAO(service);
		BeanSQL query = dao.getQuerySQL();
		order.setActionName(this.getClass().getName());
		order.setFunctionName("paySuccess");
		order.setApplyTime(new Date());
		query.createSaveSql(order);
		if (dao.update() > 0) {
			res.setData(order);
			res.setMessage("保存成功！");
		} else {
			res.setSuccess(false);
			res.setMessage("保存失败！");
		}
		return res;
	}

	/**
	 * 调用微信支付接口
	 * 
	 * @param weixinName
	 * @param request
	 * @param order
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/{weixinName}/pay.do")
	public Map<String, String> applyPay(@PathVariable("weixinName") String weixinName, HttpServletRequest request,
			WeixinOrderBean order) {
		Map<String, String> result = new HashMap<>();
		Map<String, Object> params = WebUtils.getRequestData(request);
		WeixinService wc = WeixinUtils.getWeixinBean(weixinName);
		// 1.获取统一下单信息
		WxPayUnifiedOrderRequest unified = WxPayUnifiedOrderRequest.newBuilder().openid(order.getOpenId())
				.outTradeNo(order.getOrderId()) // 订单编号
				.totalFee(BaseWxPayRequest.yuanToFen(order.getOrderFee())) // 订单金额
				.body(params.get("body").toString()).tradeType("JSAPI").spbillCreateIp(params.get("ip").toString())
				.notifyUrl(wc.getWxConfigBean().getServerUrl() + "/wechat/" + weixinName + "/any/notify.do").build();
		unified.setSignType("MD5");
		try {
			WxPayUnifiedOrderResult payInfo = wc.getPayService().unifiedOrder(unified);
			result.put("appId", wc.getConfigStorage().getAppId());
			String time = Long.toString(System.currentTimeMillis());
			result.put("timeStamp", time);
			result.put("nonceStr", payInfo.getNonceStr());
			result.put("package", "prepay_id=" + payInfo.getPrepayId());
			result.put("signType", "MD5");
			String paySign = WxPaySignatureUtils.signature(result, wc.getPayConfig().getMchKey());
			result.put("paySign", paySign);
			result.put("success", "true");
		} catch (WxPayException e) {
			e.printStackTrace();
			result.put("success", "false");
			result.put("message", e.getMessage());
		}
		return result;
	}

	/**
	 * 接受微信支付接口的回调函数
	 * 
	 * @param weixinName
	 * @param request
	 * @param response
	 */
	@RequestMapping("/{weixinName}/any/notify.do")
	public void applyPayNotify(@PathVariable("weixinName") String weixinName, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			synchronized (this) {
				WeixinService wc = WeixinUtils.getWeixinBean(weixinName);
				Map<String, String> kvm = XMLUtil.parseRequestXmlToMap(request);
				System.out.println(kvm);
				if (SignUtils.checkSign(kvm, null, wc.getPayConfig().getMchKey())) {
					if ("SUCCESS".equals(kvm.get("return_code")) && "SUCCESS".equals(kvm.get("result_code"))) {
						String orderId = kvm.get("out_trade_no");
						Service service = new Service();
						try {
							WeixinOrderBean order = DBUtils.getBean(service, WeixinOrderBean.class, orderId);// 根据订单编号查找订单详情
							Object bean = DataUtils.getInstance(order.getActionName());// 根据订单详情获取回调处理的实体类
							ClassUtils.execute(bean, order.getFunctionName(), new Object[] { service, order });// 执行指定的回调方法
							service.commit();
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							service.close();
						}
						logger.info("out_trade_no: " + kvm.get("out_trade_no") + " pay SUCCESS!");
						response.getWriter().write(
								"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
					} else {
						this.logger.error("out_trade_no: " + kvm.get("out_trade_no") + " result_code is FAIL");
						response.getWriter().write(
								"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[result_code is FAIL]]></return_msg></xml>");
					}
				} else {
					response.getWriter().write(
							"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[check signature FAIL]]></return_msg></xml>");
					this.logger.error("out_trade_no: " + kvm.get("out_trade_no") + " check signature FAIL");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 测试订单支付完成后处理
	 * 
	 * @param request
	 * @param service
	 * @param bean
	 * @return
	 */
	public PageBean paySuccess(Service service, WeixinOrderBean bean) {
		PageBean res = new PageBean();
		BeanDAO dao = new BeanDAO(service);
		BeanSQL query = dao.getQuerySQL();
		// 更新微信订单状态
		bean.setStatus(WeixinOrderBean.STATUS_OK);
		bean.setPayTime(new Date());
		query.createUpdateSql(bean);
		if (dao.update() > 0) {
			res.setData(bean);
			res.setMessage("保存成功！");
		} else {
			res.setSuccess(false);
			res.setMessage("保存失败！");
		}
		return res;
	}
}